home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 26
/
Cream of the Crop 26.iso
/
program
/
wdj0897.zip
/
DEFGEN.ZIP
/
DEFGEN.C
Wrap
C/C++ Source or Header
|
1997-05-23
|
15KB
|
490 lines
/* bcc32 -w -DSTRICT defgen.c
* --OR--
* cl /W3 /DSTRICT defgen.c
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRUE (1)
#define FALSE (0)
#define MAX_LINE (512)
#define MAX_DEFS (128)
#define MAX_ARGS (32)
#define MAX_NEST (32)
/* forward declarations */
int SetOptions(int Count, char** Args);
void Generate(const char* Filename);
void Usage(void);
/* Program options set via command-line parameters */
int Win16 = FALSE; /* -Win16 */
int BorImp = FALSE; /* -bi (Borland import) */
int BorExp = FALSE; /* -be (Borland export) */
int Microsoft = TRUE;
int GenOrd = FALSE; /* -g (generate ordinals) */
int StripOrd = FALSE; /* -s (strip ordinals) */
const char* Defs[MAX_DEFS]; /* -DName=val */
int NDefs = 0;
int main(int Count, char** Args)
{
int FirstFile = SetOptions(Count, Args);
while(FirstFile < Count)
Generate(Args[FirstFile++]);
return EXIT_SUCCESS;
}
int SetOptions(int Count, char** Args)
{
int iArg;
for(iArg = 1; iArg < Count; ++iArg)
{
if(Args[iArg][0] != '-')
break;
else switch(tolower(Args[iArg][1]))
{
case 'b' : /* Borland import or export */
if(!strcmpi(Args[iArg], "-bi"))
{
Microsoft = FALSE;
BorExp = FALSE;
BorImp = TRUE;
}
else if(!strcmpi(Args[iArg], "-be"))
{
Microsoft = FALSE;
BorImp = FALSE;
BorExp = TRUE;
}
else
Usage();
break;
case 's' : StripOrd = !StripOrd; break;
case 'g' : GenOrd = !GenOrd; break;
case 'd' :
Defs[NDefs++] = Args[iArg]+2;
break;
case 'w' :
if(!strcmpi(Args[iArg], "-win16"))
{
Win16 = TRUE;
break;
}
else if(!strcmpi(Args[iArg], "-win32"))
{
Win16 = FALSE;
break;
}
default : Usage(); break;
}
}
if(iArg >= Count)
Usage();
return iArg;
}
enum
{
STATE_SKIP = 0x0001, STATE_IF = 0x0002, STATE_ELSE = 0x0004,
STATE_ELSEIF= 0x0008, STATE_ENDIF = 0x0010, STATE_COMMAND=0x0020,
STATE_ERR = 0x8000
};
const char*LineType(const char* Line, int* Type)
{
int Result = 0;
int Len=0;
if(*Line == '!')
{
++Line;
while(isspace(*Line)) /* skip white space */
++Line;
if(!strnicmp(Line, "if", 2) && isspace(Line[Len=2]))
Result = STATE_IF;
else if(!strnicmp(Line, "else", 4) && isspace(Line[Len=4]))
Result = STATE_ELSE;
else if(!strnicmp(Line, "elseif", 6) && isspace(Line[Len=6]))
Result = STATE_ELSEIF;
else if(!strnicmp(Line, "endif", 5) && isspace(Line[Len=5]))
Result = STATE_ENDIF;
else
Result = STATE_ERR;
}
else if(Line[0] && !isspace(Line[0]))
Result = STATE_COMMAND;
*Type = Result;
return Line + Len;
}
size_t ExpandMacro(const char* Arg, char* Out)
{
size_t NameLen;
int i;
char Name[MAX_LINE];
*Out = '\0';
Arg += 2;
for(i = 0; *Arg && *Arg != ')'; ++i)
Name[i] = *Arg++;
Name[i] = '\0';
NameLen = strlen(Name);
/* use command-line definition, if found */
for(i = 0; i < NDefs; ++i)
if(!strncmp(Defs[i], Name, NameLen))
{
strcpy(Out, Defs[i]+NameLen+1);
break;
}
/* else, use environment definition, if found */
if(i >= NDefs)
{
char *EnvDef = getenv(Name);
if(EnvDef)
strcpy(Out, EnvDef);
else /* else, refer to builtins */
{
int *Value = 0;
if(!strcmpi(Name, "Win16"))
Value = &Win16;
else if(!strcmpi(Name, "Win32"))
Value = &Win16;
else if(!strcmpi(Name, "BorImp"))
Value = &BorImp;
else if(!strcmpi(Name, "BorExp"))
Value = &BorExp;
else if(!strcmpi(Name, "StripOrd"))
Value = &StripOrd;
else if(!strcmpi(Name, "GenOrd"))
Value = &GenOrd;
if(Value)
if(!strcmpi(Name, "Win32"))
strcpy(Out, (!*Value) ? "1" : "0");
else
strcpy(Out, *Value ? "1" : "0");
}
}
return NameLen + 3;
}
int GetCondition(const char* Str)
{
int Condition = FALSE;
int Not = FALSE;
char Expanded[MAX_LINE];
while(isspace(*Str)) ++Str; /* skip white space */
if(*Str == '!')
{
Not = TRUE;
++Str;
while(isspace(*Str)) ++Str; /* skip white space */
}
if(*Str)
{
char* Out = Expanded;
while(*Str && !isspace(*Str))
if(*Str == '$' && Str[1] == '(')
{
size_t Len = ExpandMacro(Str, Out);
Str += Len;
Out += strlen(Out);
}
else
*Out++ = *Str++;
*Out = '\0';
if(Expanded[0] && strcmp(Expanded, "0"))
Condition = TRUE;
}
return Not ? !Condition : Condition;
}
void FixName(const char*In, char* Out, int Cdecl)
{
char Upper[MAX_LINE];
strcpy(Upper, In);
strupr(Upper);
if(!Cdecl)
if(Win16)
strcpy(Out, Upper);
else
strcpy(Out, In);
else
if(Win16)
sprintf(Out, "_%s", In, Upper);
else if(BorExp)
sprintf(Out, "%s=_%s", In, In);
else if(BorImp)
sprintf(Out, "_%s=%s", In, In);
else
sprintf(Out, "%s", In);
}
void DoExport(char* Line)
{
static int OrdCount = 0;
static char OrdStr[8];
int Unicode = FALSE;
int Cdecl = FALSE;
int ResName = FALSE;
int NoName = FALSE;
int NoData = FALSE;
int Data = FALSE;
int Private = FALSE;
const char* FuncName= 0;
const char* Ordinal = 0;
const char* ParmCnt = 0;
char* Rover = Line;
while(*Rover)
{
char* Token;
while(isspace(*Rover)) ++Rover; /* skip white space */
if(*Rover)
{
Token = Rover;
while(*Rover && !isspace(*Rover)) ++Rover;
if(*Rover)
*Rover++ = '\0';
if(!strcmpi(Token, "residentname"))
ResName = TRUE;
else if(!strcmpi(Token, "nodata"))
NoData = TRUE;
else if(!strcmpi(Token, "noname"))
NoName = TRUE;
else if(!strcmpi(Token, "data"))
Data = TRUE;
else if(!strcmpi(Token, "private"))
Private = TRUE;
else if(!strcmpi(Token, "-U"))
Unicode = TRUE;
else if(!strcmpi(Token, "-c"))
Cdecl = TRUE;
else if(*Token == '@' && isdigit(Token[1]))
{
if(StripOrd) /* stripping takes precedence */
;
else
Ordinal = Token;
}
else if(isdigit(*Token))
ParmCnt = Token;
else if(FuncName)
{
fprintf(stderr,
"Unknown export param: '%s'\n", Token);
Usage();
}
else
FuncName = Token;
}
}
if(FuncName)
{
int Times = (!Win16 && Unicode)? 2 : 1;
int i;
char* Suffix[] = {"A", "W"};
if(GenOrd) /* if generating our own ordinals */
{
sprintf(OrdStr, "@%d", ++OrdCount);
Ordinal = OrdStr;
}
for(i = 0; i < Times; ++i)
{
char UniName[MAX_LINE];
char FixedName[MAX_LINE];
char FixedOrd[32];
strcpy(UniName, FuncName);
if(Ordinal)
strcpy(FixedOrd, Ordinal);
if(Times > 1)
{
strcat(UniName, Suffix[i]);
if(Ordinal && i > 0)
sprintf(FixedOrd, "@%d", GenOrd ? ++OrdCount :
atoi(Ordinal+1)+1);
}
if(Ordinal && NoName && (Microsoft || !Win16))
strcat(FixedOrd, " NONAME");
FixName(UniName, FixedName, Cdecl);
printf(" %s %s %s %s %s %s %s\n",
FixedName,
Ordinal ? FixedOrd : "",
(ResName&&!NoName&&!(Microsoft&&!Win16))
?"RESIDENTNAME" : "",
(NoData&&!(Microsoft&&!Win16))
? "NODATA" : "",
(Data&&Microsoft&&!Win16)
? "DATA" : "",
(ParmCnt&&!(Microsoft&&!Win16))
? ParmCnt : "",
(Private&&Microsoft)
? "PRIVATE" : ""
);
}
}
else
printf(";%s", Line);
}
void Generate(const char* FileName)
{
extern int DoLine(char*Line, int State);
char Line[MAX_LINE];
int DoingExports = FALSE;
int Stack[MAX_NEST];
int Sp = -1;
int Skipping = 0x0000;
FILE* In = fopen(FileName, "r");
if(!In) /* if can't open file, notify and exit */
{
perror(FileName);
Usage();
}
while(fgets(Line, sizeof(Line)-1, In))
{
int Type;
const char* Args;
Args = LineType(Line, &Type);
if(Type == STATE_IF)
{
Stack[++Sp] = Skipping;
Stack[++Sp] = STATE_IF;
if(!Skipping)
Skipping = !GetCondition(Args);
Stack[Sp] |= Skipping;
}
else if(Type == STATE_ELSE)
{
if(Sp < 1 || !(Stack[Sp]&STATE_IF))
fprintf(stderr, "%s: !else with no matching !if\n",
FileName);
else
{
Stack[Sp] = (Stack[Sp] ^ STATE_IF) | STATE_ELSE;
Skipping = !(Stack[Sp]&STATE_SKIP);
}
}
else if(Type == STATE_ELSEIF)
{
if(Sp < 1 || !(Stack[Sp]&STATE_IF))
fprintf(stderr, "%s: !elseif with no matching !if\n",
FileName);
else
{
Skipping = STATE_SKIP;
if(Stack[Sp]&STATE_SKIP)
{
if(GetCondition(Args))
{
Stack[Sp] ^= STATE_SKIP;
Skipping = FALSE;
}
}
}
}
else if(Type == STATE_ENDIF)
{
if(Sp < 1 || !(Stack[Sp]&(STATE_IF|STATE_ELSE)))
fprintf(stderr, "%s: !endif with no matching !if\n",
FileName);
else
{
--Sp; /* pop off if/else */
Skipping = Stack[Sp--];
}
}
else if(Type == STATE_ERR)
fprintf(stderr, "%s: Unknown directive (%s)\n",
FileName, Line);
else if(!Skipping)
{
if(DoingExports)
DoExport(Line);
else
{
char Macro[MAX_LINE];
char* In = Line;
while(*In)
{
if(In[0] == '$' && In[1] == '(')
{
size_t Len = ExpandMacro(In, Macro);
In += Len;
printf("%s", Macro);
}
else
putchar(*In++);
}
}
if(Type == STATE_COMMAND)
DoingExports = !strncmp(Line, "EXPORTS", 7);
}
}
fclose(In);
}
void PutArg(const char* Arg)
{
while(*Arg)
if(*Arg == '$' && Arg[1] == '(')
{
size_t NameLen;
int i;
char Name[MAX_LINE];
Arg += 2;
for(i = 0; *Arg && *Arg != ')'; ++i)
Name[i] = *Arg++;
Name[i] = '\0';
NameLen = strlen(Name);
if(*Arg == ')')
++Arg;
/* use command-line definition, if found */
for(i = 0; i < NDefs; ++i)
if(!strncmp(Defs[i], Name, NameLen))
{
printf("%s", Defs[i]+NameLen+1);
break;
}
/* else, use environment definition, if found */
if(i >= NDefs)
{
char *EnvDef = getenv(Name);
if(EnvDef)
printf("%s", EnvDef);
}
}
else
putchar(*Arg++);
}
void Usage(void)
{
fprintf(stderr,
"Usage:\n"
" defgen {-options} infile1 {... infilen}\n"
"Where:\n"
" -be <- for Borland exports\n"
" -bi <- for Borland import library\n"
" -DName=val <- Define text macro\n"
" -g <- generate ordinals\n"
" -s <- strip existing ordinals\n"
" -Win16 <- produce Win16 .DEF file\n"
"(writes to standard output, default is 32-bit VC++)\n"
);
exit(EXIT_FAILURE);
}